﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Web.Services;

using Microsoft.DeepZoomTools;

using TechPath.DCM.Sharepoint.Services.Data;
using TechPath.DCM.Sharepoint.Services.Util;

namespace TechPath.DCM.Sharepoint.Services
{
    /// <summary>
    /// Summary description for DeepZoomTileService
    /// </summary>
    [WebService(Namespace = "http://techpath.com/DCM/DeepZoom/TileService/2009/03")]
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
    [System.ComponentModel.ToolboxItem(false)]
    // To allow this Web Service to be called from script, using ASP.NET AJAX, uncomment the following line. 
    // [System.Web.Script.Services.ScriptService]
    public class DeepZoomTileService : System.Web.Services.WebService
    {

        [WebMethod]
        public string GenerateDeepZoomImage(string sourceImageUri, string sourceImageKey)
        {
            ImageCreator ic = new ImageCreator();

            ic.TileSize = Config.TileSize;
            ic.TileFormat = Config.TileFormat;
            ic.ImageQuality = Config.TileImageQuality;
            ic.TileOverlap = Config.TileOverlapSize;
            ic.ServerFormat = Config.ServerFormat;

            string privateTargetPath = GetPrivateTargetFilePath(sourceImageKey, ic.ServerFormat);
            string publicTargetPath = GetPublicTargetFilePath(sourceImageKey, ic.ServerFormat);

            Directory.CreateDirectory(Path.GetDirectoryName(privateTargetPath));

            ic.Create(sourceImageUri, privateTargetPath);

            DzImage image = new DzImage(sourceImageKey, sourceImageUri, publicTargetPath, privateTargetPath, DateTime.Now);
            DeepZoomDataAccess.SaveImage(image);

            return publicTargetPath;
        }

        [WebMethod]
        public DzGenerateCollectionResult GenerateDeepZoomCollection(string[] sourceImageKeys)
        {
            CollectionCreator cc = new CollectionCreator();

            cc.TileSize = Config.TileSize;
            cc.TileFormat = Config.TileFormat;
            cc.ImageQuality = Config.TileImageQuality;
            cc.TileOverlap = Config.TileOverlapSize;
            cc.ServerFormat = Config.ServerFormat;
            cc.MaxLevel = Config.CollectionLevel;

            string targetFolderName = "col_" + Guid.NewGuid().ToString();
            string target = GetPrivateTargetFilePath(targetFolderName, cc.ServerFormat);

            Directory.CreateDirectory(Path.GetDirectoryName(target));

            DzImage missingImage = DeepZoomDataAccess.GetImageBySourceImageKey(Config.MissingImageKey);

            List<string> foundImageKeys = new List<string>();
            List<string> imageFiles = new List<string>();
            foreach (string sourceImageKey in sourceImageKeys)
            {
                DzImage source = DeepZoomDataAccess.GetImageBySourceImageKey(sourceImageKey);

                if (source != null)
                {
                    imageFiles.Add(source.PrivateDzImageUri);
                    foundImageKeys.Add(sourceImageKey);
                }
                else if (Config.SubstituteMissingImage)
                {
                    imageFiles.Add(missingImage.PrivateDzImageUri);
                    foundImageKeys.Add(sourceImageKey);
                }
            }

            cc.Create(imageFiles, target);

            DzGenerateCollectionResult result = new DzGenerateCollectionResult();
            result.CollectionUri = GetPublicTargetFilePath(targetFolderName, cc.ServerFormat);
            result.IncludedImageKeys = foundImageKeys.ToArray();

            return result;
        }

        private static string GetPrivateTargetPath(string sourceUri)
        {
            return Path.Combine(Config.PrivateRootTilePath, MakeSafePath(sourceUri));
        }

        private static string GetPublicTargetPath(string sourceUri)
        {
            return new Uri(new Uri(Config.PublicRootTilePath), MakeSafePath(sourceUri)).ToString();
        }

        private static string GetPrivateTargetFilePath(string sourceKey, ServerFormats format)
        {
            string extension = format == ServerFormats.SmoothStreaming ? ".ism" : ".xml";
            string targetPath = GetPrivateTargetPath(sourceKey);
            return Path.Combine(targetPath, "dz_image" + extension).ToLower();
        }

        private static string GetPublicTargetFilePath(string sourceKey, ServerFormats format)
        {
            string extension = format == ServerFormats.SmoothStreaming ? ".ism" : ".xml";
            string targetPath = GetPublicTargetPath(sourceKey);
            return new Uri(new Uri(targetPath + "/"), "dz_image" + extension).ToString().ToLower();
        }

        private static string MakeSafePath(string path)
        {
            char[] badChars = Path.GetInvalidPathChars();
            foreach (char badChar in badChars)
                path = path.Replace(badChar, '_');
            path = path.Replace(':', '_');
            path = path.Replace('/', '_');
            path = path.Replace('\\', '_');
            path = path.Replace('?', '_');

            return path;
        }

        [WebMethod]
        public string GetDeepZoomImageUri(string sourceImageKey)
        {
            DzImage image = DeepZoomDataAccess.GetImageBySourceImageKey(sourceImageKey);
            if (image != null)
                return image.PublicDzImageUri;
            else
                return null;
        }
    }
}
